package com.todo.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.todo.dao.TeamInfoDAO;
import com.todo.dto.Result;
import com.todo.dto.TeamMemberChangeDTO;
import com.todo.dto.TeamMemberDTO;
import com.todo.dto.UserDTO;
import com.todo.entity.Team;
import com.todo.entity.TeamInfo;
import com.todo.entity.User;
import com.todo.mapper.TeamInfoMapper;
import com.todo.mapper.TeamMapper;
import com.todo.mapper.UserMapper;
import com.todo.service.ITeamService;
import com.todo.utils.TIDUtil;
import com.todo.utils.UserHolder;
import com.todo.vo.TeamMemberVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@Slf4j
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements ITeamService {
    @Resource
    private TeamMapper teamMapper;

    @Resource
    private TeamInfoMapper teamInfoMapper;

    @Resource
    private TIDUtil tidUtil;

    @Resource
    private UserMapper userMapper;

    /**
     * 从线程获取用户uid，进行创建 传入团队名
     */
    @Override
    public Result createTeam(String teamName) {
        //1.从线程中获取uid
        UserDTO userDTO = UserHolder.getUser();
        //1.1校验获取等对象是否为空
        if (ObjectUtil.isEmpty(userDTO) || userDTO==null){
            //返回错误信息，用户未登录
            return Result.fail("用户未登录，创建失败");
        }
        String uid = userDTO.getUid();
        //2.创建team(team_base_info)实体对象
        Team team = new Team();
        //3.从tid号池中获取一个tid
        String tid = tidUtil.getTID();
        //4.初始化team(团队基础信息)对象，填入数据
        /*
          团队主键id自动生成
          团队tid
          团队名称 teamName
          团队头像 默认：
          团队类别：默认 后期修改
          团队聚餐次数：默认0
          团队团建次数：默认0
          团队创建时间now
          团队基础信息修改时间now
         */
        team.setTid(tid);
        team.setTName(teamName);
        LocalDateTime now = LocalDateTime.now();
        team.setCreateTime(now);
        team.setUpdateTime(now);
        //团队基础信息插入数据库
        teamMapper.insert(team);
        //创建团队详细信息对象
        TeamInfo teamInfo = new TeamInfo();
        /*
          tid
          tOwner
          List<TeamMemberDTO>
          M count
          创建
          修改
         */
        teamInfo.setTid(tid);
        teamInfo.setTOwner(uid);
        teamInfo.setTMemberCount(1);
        teamInfo.setUpdateTime(now);
        teamInfo.setCreateTime(now);
        List<TeamMemberDTO> teamMemberDTOList = new ArrayList<>();
        //创建 初始化TeamMemberDTO对象
        TeamMemberDTO teamMemberDTO = new TeamMemberDTO();
        //通过uid获取用户对象
        User user = userMapper.selectByUid(uid);
        BeanUtils.copyProperties(user,teamMemberDTO);
        teamMemberDTO.setPrivilege(TeamMemberDTO.PRIVILEGE_OWNER);
        teamMemberDTO.setJoinTime(now);
        teamMemberDTOList.add(teamMemberDTO);
        teamInfo.setTMemberList(teamMemberDTOList);

        //转DAO
        TeamInfoDAO teamInfoDAO = teamInfo.toTeamInfoDAO();
        //团队详细信息插入数据库
        teamInfoMapper.insert(teamInfoDAO);
        //返回tid值
        return Result.ok(tid);
    }

    /**
     * 邀请用户加入
     * @param uid
     * @param tid
     * @return
     */
    @Override
    public Result inviteMember(String uid, String tid) {
        //验证当前用户是否有操作权限
        UserDTO userDTO = UserHolder.getUser();
        //获取用户uid
        String uidOperator = userDTO.getUid();
        //查询需要添加的用户信息
        User user = userMapper.selectByUid(uid);
        //判断用户是否存在
        if (user == null) {
            log.info("用户不存在：{}",uid);
            return Result.fail("用户不存在");
        }
        //获取当前团队详细信息对象
        TeamInfoDAO teamInfoDAO = teamInfoMapper.selectById(tid);
        //校验团队是否存在
        if (teamInfoDAO == null) {
            log.info("该团队不存在：{}",tid);
            return Result.fail("团队不存在");
        }
        //在成员列表中添加该成员
        TeamInfo teamInfo = teamInfoDAO.toTeamInfo();
        List<TeamMemberDTO> tMemberList = teamInfo.getTMemberList();
        //判断操作的用户是否有权限
        boolean verifyPrivilege = verifyPrivilege(TeamMemberDTO.PRIVILEGE_MANAGER, tMemberList, uidOperator);
        if (!verifyPrivilege){
            return Result.fail("权限不足");
        }
        //将用户转为列表用户对象
        TeamMemberDTO teamMemberDTO = new TeamMemberDTO();
        BeanUtils.copyProperties(user,teamMemberDTO);//已有uid ，icon，status,name
        //设置加入时间
        teamMemberDTO.setJoinTime(LocalDateTime.now());
        //设置权限 默认普通用户权限
        teamMemberDTO.setPrivilege(TeamMemberDTO.PRIVILEGE_MEMBER);
        //添加成员进入列表
        tMemberList.add(teamMemberDTO);
        //更新teamInfo对象
        teamInfo.setTMemberList(tMemberList);
        teamInfo.setTMemberCount(teamInfo.getTMemberCount()+1);
        //转DAO
        TeamInfoDAO newTeamInfoDAO = teamInfo.toTeamInfoDAO();
        int i = teamInfoMapper.updateById(newTeamInfoDAO);
        if (i>0){
            return Result.ok("添加成员成功："+uid);
        }
        return Result.fail("添加成员数据库操作失败："+uid);
        //操作的用户不在群或权限不足
    }

    /**
     * 通过用户uid以及团队tid 删除团队中该成员 退群操作
     * @param uid
     * @param tid
     * @return
     */
    @Override
    public Result delMember(String uid, String tid) {
        //获取当前操作用户uid
        UserDTO userDTO = UserHolder.getUser();
        String uidOperator = userDTO.getUid();
        //获取团队对象
        TeamInfoDAO teamInfoDAO = teamInfoMapper.selectById(tid);
        TeamInfo teamInfo = teamInfoDAO.toTeamInfo();
        //获取成员列表
        List<TeamMemberDTO> tMemberList = teamInfo.getTMemberList();
        //退群操作
        //团队成员退群操作
        if (uidOperator.equals(uid) && !uid.equals(teamInfo.getTOwner())){
            //删除该团队成员
            tMemberList.removeIf(teamMemberDTO -> teamMemberDTO.getUid().equals(uid));
            //更新团队信息对象
            teamInfo.setTMemberList(tMemberList);
            //更新成员变量
            teamInfo.setTMemberCount(teamInfo.getTMemberCount()-1);
            //转DAO
            TeamInfoDAO newTeamInfoDAO = teamInfo.toTeamInfoDAO();
            //插入数据库
            int i = teamInfoMapper.updateById(newTeamInfoDAO);
            if (i>0){
                return Result.ok("退群成功："+uid);
            }
            return Result.fail("数据库修改失败，未进行删除操作");
        }

        //验证当前用户权限
        boolean verifyPrivilege = verifyPrivilege(TeamMemberDTO.PRIVILEGE_MANAGER, tMemberList, uidOperator);

        //验证当前操作用户的权限
        if (!verifyPrivilege){
            return Result.fail("权限不足");
        }
        //验证被操作用户权限 团队所有者、管理者无法被直接删除
        boolean verifyPrivilege1 = verifyPrivilege(TeamMemberDTO.PRIVILEGE_MANAGER, tMemberList, uid);
        if (verifyPrivilege1){
            return Result.fail("团队所有者、管理员不能直接被移出群");
        }
        //删除该团队成员
        tMemberList.removeIf(teamMemberDTO -> teamMemberDTO.getUid().equals(uid));
        //更新团队信息对象
        teamInfo.setTMemberList(tMemberList);
        //更新成员变量
        teamInfo.setTMemberCount(teamInfo.getTMemberCount()-1);
        //转DAO
        TeamInfoDAO newTeamInfoDAO = teamInfo.toTeamInfoDAO();
        //插入数据库
        int i = teamInfoMapper.updateById(newTeamInfoDAO);
        if (i>0){
            return Result.ok("移除成员成功："+uid);
        }
        return Result.fail("数据库修改失败，未进行删除操作");
    }

    /**
     * 删除团队
     * @param tid
     * @return
     */
    @Override
    public Result dropTeam(String tid) {
        //获取当前用户uid
        String uidOperator = UserHolder.getUser().getUid();
        //获取团队成员列表
        TeamInfoDAO teamInfoDAO = teamInfoMapper.selectById(tid);
        TeamInfo teamInfo = teamInfoDAO.toTeamInfo();
        List<TeamMemberDTO> tMemberList = teamInfo.getTMemberList();
        //验证用户权限，群主才有权限
        boolean privilege = verifyPrivilege(TeamMemberDTO.PRIVILEGE_OWNER, tMemberList, uidOperator);
        if (!privilege){
            return Result.fail("权限不足");
        }
        QueryWrapper<Team> wrapper = new QueryWrapper<>();
        wrapper.eq("tid",tid);
        int deleteTeam = teamMapper.delete(wrapper);
        int deleteTeamInfo = teamInfoMapper.deleteById(tid);
        String text = "";
        if (deleteTeam > 0){
            text += "团队信息基础删除成功";
        }
        if (deleteTeamInfo>0){
            text += ",团队详细信息删除成功";
        }
        return Result.ok(text);
    }

    /**
     * 根据tid获取团队信息
     * @param tid
     * @return
     */
    @Override
    public Result getTeam(String tid) {
        Team team = teamMapper.selectById(tid);
        if (ObjectUtil.isEmpty(team)){
            return Result.fail("查询团队信息失败，无此tid："+tid);
        }
        return Result.ok(team);
    }

    /**
     * 拆寻团队详细信息
     * @param tid
     * @return
     */
    @Override
    public Result getTeamDetail(String tid) {
        TeamInfoDAO teamInfoDAO = teamInfoMapper.selectById(tid);
        if (ObjectUtil.isEmpty(teamInfoDAO)){
            return Result.fail("查询团队详情信息失败，无此tid："+tid);
        }
        TeamInfo teamInfo = teamInfoDAO.toTeamInfo();
        return Result.ok(teamInfo);
    }

    /**
     * 根据团队tid查询团队成员列表
     * @param tid
     * @return
     */
    @Override
    public Result queryTeamMemberList(String tid) {
        TeamInfoDAO teamInfoDAO = teamInfoMapper.selectById(tid);
        if (ObjectUtil.isEmpty(teamInfoDAO)){
            return Result.fail("该团队不存在:"+tid);
        }
        //查询并组装返回对象
        List<TeamMemberVO> teamMemberVOList = new ArrayList<>();
        List<TeamMemberDTO> tMemberList = teamInfoDAO.toTeamInfo().getTMemberList();
        for (TeamMemberDTO t: tMemberList) {
            TeamMemberVO teamMemberVO = new TeamMemberVO();
            teamMemberVO.setPrivilege(t.getPrivilege());
            teamMemberVO.setJoinTime(t.getJoinTime());
            teamMemberVO.setUid(t.getUid());
            //查询用户表获取用户登录状态、头像、名字
            User user = userMapper.selectByUid(t.getUid());
            teamMemberVO.setUName(user.getUName());
            teamMemberVO.setUStatus(user.getUStatus());
            teamMemberVO.setUIcon(user.getUIcon());
            teamMemberVOList.add(teamMemberVO);
        }
        return Result.ok(teamMemberVOList);
    }

    @Override
    public Result changePrivilege(TeamMemberChangeDTO teamMemberChangeDTO) {
        //获取当前操作用户的uid
        String uidOperator = UserHolder.getUser().getUid();
        //不能更改自己的权限
        if (uidOperator.equals(teamMemberChangeDTO.getUid())){
            return Result.fail("无法修改自己的权限");
        }
        //获取团队详细信息
        TeamInfoDAO teamInfoDAO = teamInfoMapper.selectById(teamMemberChangeDTO.getTid());
        TeamInfo teamInfo = teamInfoDAO.toTeamInfo();

        //获取团队列表
        List<TeamMemberDTO> tMemberList = teamInfo.getTMemberList();
        //验证当前操作用户的权限 只有团队所有者可以修改他人权限
        boolean verifyPrivilege = teamInfo.getTOwner().equals(uidOperator);
        if (!verifyPrivilege){
            return Result.fail("权限不足");
        }
        //若传入的权限是0，那么视为转让团队所有者
        if (teamMemberChangeDTO.getPrivilege()==0){
            //修改团队列表中对应数据的privilege
            for (TeamMemberDTO teamMemberDTO : tMemberList){
                if (teamMemberDTO.getUid().equals(teamMemberChangeDTO.getUid())){
                    //修改权限
                    teamMemberDTO.setPrivilege(TeamMemberDTO.PRIVILEGE_OWNER);
                }
                if (teamMemberDTO.getUid().equals(uidOperator)){
                    //改为普通成员
                    teamMemberDTO.setPrivilege(TeamMemberDTO.PRIVILEGE_MANAGER);
                }
            }
            //修改团队详细信息中的所有者uid
            teamInfo.setTOwner(teamMemberChangeDTO.getUid());
        }else {
            //修改团队列表中对应数据的privilege
            for (TeamMemberDTO teamMemberDTO : tMemberList){
                if (teamMemberDTO.getUid().equals(teamMemberChangeDTO.getUid())){
                    //修改权限
                    teamMemberDTO.setPrivilege(teamMemberChangeDTO.getPrivilege());
                    break;
                }
            }
        }

        //转DAO
        teamInfoDAO = teamInfo.toTeamInfoDAO();
        //更新数据库
        int i = teamInfoMapper.updateById(teamInfoDAO);
        if (i>0){
            return Result.ok("");
        }
        return Result.fail("数据库未改变");
    }

    /**
     * 验证用户权限
     * @param privilege 最低权限
     * @param teamMemberDTOList 群聊成员列表
     * @param uid 需要验证的用户uid
     * @return
     */
    private boolean verifyPrivilege(int privilege,List<TeamMemberDTO> teamMemberDTOList,String uid){
        for (TeamMemberDTO teamMemberDTO : teamMemberDTOList){
            if (teamMemberDTO.getUid().equals(uid)){
                if (teamMemberDTO.getPrivilege()<=privilege){
                    return true;
                }
                return false;
            }
        }
        return false;
    }
}
